const myReduce = require("./template.js")

function testMyReduce() {
  console.log("=== 手写 reduce 测试 ===")

  console.log(
    "1. 基本求和功能:",
    (() => {
      const arr = [1, 2, 3, 4, 5]
      const result = myReduce(arr, (acc, curr) => acc + curr, 0)
      return result === 15
    })()
  )

  console.log(
    "2. 无初始值求和:",
    (() => {
      const arr = [1, 2, 3, 4, 5]
      const result = myReduce(arr, (acc, curr) => acc + curr)
      return result === 15
    })()
  )

  console.log(
    "3. 空数组无初始值:",
    (() => {
      try {
        myReduce([], (acc, curr) => acc + curr)
        return false // 应该抛出错误
      } catch (e) {
        return true
      }
    })()
  )

  console.log(
    "4. 空数组有初始值:",
    (() => {
      const result = myReduce([], (acc, curr) => acc + curr, 10)
      return result === 10
    })()
  )

  console.log(
    "5. 字符串拼接:",
    (() => {
      const arr = ["hello", " ", "world", "!"]
      const result = myReduce(arr, (acc, curr) => acc + curr, "")
      return result === "hello world!"
    })()
  )

  console.log(
    "6. 数组扁平化:",
    (() => {
      const arr = [
        [1, 2],
        [3, 4],
        [5, 6]
      ]
      const result = myReduce(arr, (acc, curr) => acc.concat(curr), [])
      return JSON.stringify(result) === JSON.stringify([1, 2, 3, 4, 5, 6])
    })()
  )

  console.log(
    "7. 对象属性统计:",
    (() => {
      const arr = [
        { name: "Alice", age: 25 },
        { name: "Bob", age: 30 },
        { name: "Charlie", age: 25 }
      ]
      const result = myReduce(
        arr,
        (acc, curr) => {
          acc[curr.name] = curr.age
          return acc
        },
        {}
      )
      return result.Alice === 25 && result.Bob === 30 && result.Charlie === 25
    })()
  )

  console.log(
    "8. 索引参数测试:",
    (() => {
      const arr = [10, 20, 30]
      const indices = []
      myReduce(
        arr,
        (acc, curr, index) => {
          indices.push(index)
          return acc + curr
        },
        0
      )
      return JSON.stringify(indices) === JSON.stringify([0, 1, 2])
    })()
  )

  console.log(
    "9. 原数组参数测试:",
    (() => {
      const arr = [1, 2, 3]
      let originalArray = null
      myReduce(
        arr,
        (acc, curr, index, original) => {
          originalArray = original
          return acc + curr
        },
        0
      )
      return originalArray === arr
    })()
  )

  console.log(
    "10. 复杂对象处理:",
    (() => {
      const arr = [
        { id: 1, value: 10 },
        { id: 2, value: 20 },
        { id: 1, value: 30 }
      ]
      const result = myReduce(
        arr,
        (acc, curr) => {
          if (!acc[curr.id]) {
            acc[curr.id] = 0
          }
          acc[curr.id] += curr.value
          return acc
        },
        {}
      )
      return result[1] === 40 && result[2] === 20
    })()
  )

  console.log(
    "11. 布尔值处理:",
    (() => {
      const arr = [true, false, true, false]
      const result = myReduce(arr, (acc, curr) => acc && curr, true)
      return result === false
    })()
  )

  console.log(
    "12. 数字类型初始值:",
    (() => {
      const arr = [1, 2, 3]
      const result = myReduce(arr, (acc, curr) => acc * curr, 1)
      return result === 6
    })()
  )

  console.log(
    "13. 字符串类型初始值:",
    (() => {
      const arr = ["b", "c", "d"]
      const result = myReduce(arr, (acc, curr) => acc + curr, "a")
      return result === "abcd"
    })()
  )

  console.log(
    "14. 数组类型初始值:",
    (() => {
      const arr = [1, 2, 3]
      const result = myReduce(
        arr,
        (acc, curr) => {
          acc.push(curr * 2)
          return acc
        },
        []
      )
      return JSON.stringify(result) === JSON.stringify([2, 4, 6])
    })()
  )

  console.log(
    "15. 单元素数组:",
    (() => {
      const arr = [42]
      const result = myReduce(arr, (acc, curr) => acc + curr, 0)
      return result === 42
    })()
  )

  console.log(
    "16. 单元素数组无初始值:",
    (() => {
      const arr = [42]
      const result = myReduce(arr, (acc, curr) => acc + curr)
      return result === 42
    })()
  )

  console.log(
    "17. 包含undefined和null:",
    (() => {
      const arr = [1, undefined, 3, null, 5]
      const result = myReduce(
        arr,
        (acc, curr) => {
          return curr !== undefined && curr !== null ? acc + curr : acc
        },
        0
      )
      return result === 9
    })()
  )

  console.log(
    "18. 回调函数返回值类型变化:",
    (() => {
      const arr = [1, 2, 3]
      const result = myReduce(
        arr,
        (acc, curr, index) => {
          return index === 1 ? "string" : acc + curr
        },
        0
      )
      return result === "string"
    })()
  )

  console.log(
    "19. 大数组性能测试:",
    (() => {
      const arr = Array.from({ length: 1000 }, (_, i) => i + 1)
      const result = myReduce(arr, (acc, curr) => acc + curr, 0)
      return result === 500500 // 1+2+...+1000 = 500500
    })()
  )

  console.log(
    "20. 与原生reduce对比:",
    (() => {
      const arr = [1, 2, 3, 4, 5]
      const nativeResult = arr.reduce((acc, curr) => acc + curr, 0)
      const myResult = myReduce(arr, (acc, curr) => acc + curr, 0)
      return nativeResult === myResult
    })()
  )

  console.log(
    "21. this上下文测试:",
    (() => {
      const obj = {
        data: [1, 2, 3, 4, 5],
        sum: function() {
          return myReduce(this.data, (acc, curr) => acc + curr, 0)
        }
      }
      const result = obj.sum()
      return result === 15
    })()
  )

  console.log(
    "22. 回调函数this绑定:",
    (() => {
      const obj = {
        multiplier: 2,
        process: function(arr) {
          return myReduce(arr, function(acc, curr) {
            return acc + (curr * this.multiplier)
          }.bind(this), 0)
        }
      }
      const result = obj.process([1, 2, 3])
      return result === 12 // (1*2) + (2*2) + (3*2) = 12
    })()
  )

  console.log(
    "23. 箭头函数this绑定:",
    (() => {
      const obj = {
        multiplier: 3,
        process: function(arr) {
          return myReduce(arr, (acc, curr) => {
            return acc + (curr * this.multiplier)
          }, 0)
        }
      }
      const result = obj.process([1, 2, 3])
      return result === 18 // (1*3) + (2*3) + (3*3) = 18
    })()
  )

  console.log(
    "24. 复杂对象this绑定:",
    (() => {
      const obj = {
        items: [{ value: 1 }, { value: 2 }, { value: 3 }],
        getTotal: function() {
          return myReduce(this.items, (acc, curr) => {
            return acc + curr.value
          }, 0)
        }
      }
      const result = obj.getTotal()
      return result === 6
    })()
  )
}

testMyReduce()
